package me.fung.keen.app.view

import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import me.fung.keen.app.Visual
import kotlin.reflect.KClass
import kotlin.reflect.KFunction
import kotlin.reflect.full.isSubclassOf
import kotlin.reflect.full.primaryConstructor
import kotlin.reflect.jvm.jvmErasure

abstract class BaseView<P : BasePresenter> : me.fung.keen.app.Visual {
    var p: P
        private set

    init {
        p = createPresenter()
    }

    private fun createPresenter(): P {
        return callConstructor(findConstructor())
    }


    @Suppress("UNCHECKED_CAST")
    private fun findConstructor(): KFunction<P>? = sequence {
        var thisClass: KClass<*> = this@BaseView::class
        while (true) {
            yield(thisClass.supertypes)
            thisClass = thisClass.supertypes.firstOrNull()?.jvmErasure ?: break
        }
    }.flatMap {
        it.flatMap { kType ->
            kType.arguments
        }.asSequence()
    }.first {
        it.type?.jvmErasure?.isSubclassOf(BasePresenter::class) ?: false
    }.let {
        it.type?.jvmErasure?.primaryConstructor as? KFunction<P>
    }

    protected open fun callConstructor(constructor: KFunction<P>?): P {
        return constructor?.call() ?: throw IllegalStateException("Need primary constructor")
    }

    @Composable
    override fun show(modifier: Modifier) {
        content(modifier)
    }
}